package world.criver;

import world.criver.data.daConfig;
import world.criver.data.daValue;

import java.lang.reflect.Constructor;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class CSqlite {
    /**
     * 创建数据库工具
     * @param path
     */
    public CSqlite(String path){
        try{
            daConfig.url="jdbc:sqlite:"+path;
            Class.forName("org.sqlite.JDBC");
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }

    /**
     * 查询
     * 返回 ArrayList
     * @param sql 查询语句
     * @return ArrayList<HashMap<String,Object>> String为字段名，Object为字段值
     */
    public List<HashMap<String,Object>> query(String sql){
        try{
            ResultSet set=daValue.ment.executeQuery(sql);
            ResultSetMetaData da= set.getMetaData();
            HashMap<String,String> title=new HashMap<>();
            for(int i=1;i<=da.getColumnCount();i++)
                title.put(da.getColumnName(i),da.getColumnTypeName(i));
            ArrayList<HashMap<String,Object>> re=new ArrayList<>();
            while(set.next()){
                HashMap<String,Object> row=new HashMap<>();
                for(String key:title.keySet()){
                    if(title.get(key).equals("TEXT"))row.put(key,set.getString(key));
                    else if(title.get(key).equals("INTEGER"))row.put(key,set.getLong(key));
                    else if(title.get(key).equals("NUMERIC"))row.put(key,set.getDouble(key));
                    else if(title.get(key).equals("REAL"))row.put(key,set.getDouble(key));
                    else if(title.get(key).equals("NONE"))row.put(key,set.getBytes(key));
                    else if(title.get(key).equals("BLOB"))row.put(key,set.getBytes(key));
                    else row.put(key,set.getBytes(key));
                }
                re.add(row);
            }
            set.close();
            return re;
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }

    /**
     * 查询
     * @param sql 查询语句
     * @param c   实体类
     * @return 返回ArrayList<Class <T>>
     */
    public <T> List<T> query(String sql, Class<T> c){
        try{
            if(c.isRecord())return new ArrayList<>();
            ArrayList<T> rows=new ArrayList<>();
            ResultSet set=daValue.ment.executeQuery(sql);
            ResultSetMetaData da= set.getMetaData();
            HashMap<String,String> title=new HashMap<>();
            for(int i=1;i<=da.getColumnCount();i++)
                title.put(da.getColumnName(i),da.getColumnTypeName(i));
            while(set.next()){
                Constructor<T> cons=c.getConstructor();
                T o=cons.newInstance();
                for(String key:title.keySet()){
                    String me="set"+key.toUpperCase().substring(0,1)+key.substring(1);
                    if(title.get(key).equals("TEXT"))c.getMethod(me, String.class).invoke(o,set.getString(key));
                    else if(title.get(key).equals("INTEGER"))c.getMethod(me, long.class).invoke(o,set.getLong(key));
                    else if(title.get(key).equals("NUMERIC"))c.getMethod(me, double.class).invoke(o,set.getDouble(key));
                    else if(title.get(key).equals("REAL"))c.getMethod(me, double.class).invoke(o,set.getDouble(key));
                    else if(title.get(key).equals("NONE"))c.getMethod(me, byte[].class).invoke(o,set.getBytes(key));
                    else if(title.get(key).equals("BLOB"))c.getMethod(me, byte[].class).invoke(o,set.getBytes(key));
                    else c.getMethod(me, String.class).invoke(o,set.getString(key));
                }
                rows.add(o);
            }
            set.close();
            return rows;
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }

    /**
     * 执行更新语句
     * @param sql
     * @return 返回执行成功行数
     */
    public int update(String sql){
        try{
            return daValue.ment.executeUpdate(sql);
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }

    /**
     * 执行无返回值语句
     * @param sql
     * @return
     */
    public boolean execute(String sql){
        try{
            return daValue.ment.execute(sql);
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }
    /**
     * 连接数据库
     * @return
     */
    public boolean connect(){
        try{
            daValue.con= DriverManager.getConnection(daConfig.url);
            daValue.ment=daValue.con.createStatement();
            return !daValue.con.isClosed();
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 关闭数据库
     * @return
     */
    public boolean close(){
        try{
            daValue.con.close();
            return daValue.con.isClosed();
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }
}
